﻿#include "FITKAbstractFESubSys.h"
#include "FITKAcousticsDiscModel.h"
#include "FITKAcousticsFEModel.h"
#include "FITKAcousticsFENodeMap.h"
#include "FITKAcousticsDiscNodeList.h"
#include "FITKFESubSysGeoProp.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Interface/FITKInterfaceModel/FITKAbstractElement.h"

#include "FITK_Interface/FITKInterfaceStructural/FITKAbaMeshPartVTK.h"
#include "FITK_Component/FITKAbaqusData/FITKAbaqusPart.h"
#include "FITK_Interface/FITKInterfaceModel/FITKElementFactory.h"
#include "FITK_Component/FITK2DMeshTools/FITKAbstractSeparatePlate.h"
#include "FITK_Interface/FITKInterfaceModel/FITKElementTri.h"

#include "FITK_Kernel/FITKCore/FITKDataRepo.h"

#include <QDebug>

#include <QSet>

namespace Acoustics
{

    FITKAbstractFESubSys::FITKAbstractFESubSys()
    {
        _geoProp = new FITKFESubSysGeoProp(this);
    }

    FITKAbstractFESubSys::~FITKAbstractFESubSys()
    {
        if (_geoProp) delete _geoProp;
    }

    FITKAbstractFESubSys::FESubSysType FITKAbstractFESubSys::getFESubSysType()
    {
        //获取子系统类型
        return FITKAbstractFESubSys::FESubSysType::FENone;
    }

    bool FITKAbstractFESubSys::updateGeoProp()
    {
        if (_geoProp) return _geoProp->updateProp();
        return false;
    }

    FITKFESubSysGeoProp* FITKAbstractFESubSys::getGeoProp()
    {
        return _geoProp;
    }

    void FITKAbstractFESubSys::setElements(QList<int>& elems)
    {
        //设置单元
        _elementsIDList = elems;
    }

    QList<int> FITKAbstractFESubSys::getNodesID()
    {
        if (_elementsIDList.isEmpty()) return QList<int>();
        //获取FE模型数据
        Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discModel)return QList<int>();
        FITKAcousticsFEModel* feModel = discModel->getFEModel();
        if (!feModel) return QList<int>();
        //获取单元列表
        FITKAcousticsFESubSysElementList* elementList = feModel->getFESubSysElementList();
        if (!elementList) return QList<int>();
        //获取全部节点
        QSet<int> nodeAll;
        for (int eleID : _elementsIDList)
        {
            //获取单元
            Interface::FITKAbstractElement* element = elementList->getElementByID(eleID);
            if (!element) continue;
            QList<int> ids = element->getAllNodes();
            //并集
            nodeAll.unite(ids.toSet());
        }
        return nodeAll.toList();
    }

    QList<int> FITKAbstractFESubSys::getElementsID()
    {
        //获取单元ID列表
        return _elementsIDList;
    }

    QList<int> FITKAbstractFESubSys::getAllElementPropID(bool* isFEProperty)
    {
        if (isFEProperty)
            *isFEProperty = false;
        //获取离散数据
        Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discModel)return QList<int>();
        //FE模型
        Acoustics::FITKAcousticsFEModel* feModel = discModel->getFEModel();
        if (!feModel)return QList<int>();
        FITKAcousticsFESubSysElementList* elementList = feModel->getFESubSysElementList();
        if (!elementList)return QList<int>();
        QList<int> propList;
        for (int eID : _elementsIDList)
        {
            bool isFE = false;
            int propID = elementList->getElementPropID(eID, &isFE);
            if (isFE && isFEProperty) *isFEProperty = true;
            if (!propList.contains(propID))
                propList.append(propID);
        }
        return propList;
    }

    QList<QString> FITKAbstractFESubSys::getAllElementPropName()
    {
        //获取属性的名称
        QList<QString> propNames;
        QList<int> propIDs = this->getAllElementPropID();
        for (int propID : propIDs)
        {
            //获取材料名称
            Core::FITKAbstractNDataObject *obj = FITKDATAREPO->getTDataByID<Core::FITKAbstractNDataObject>(propID);
            if (!obj) continue;
            propNames.append(obj->getDataObjectName());
        }
        return propNames;
    }

    int FITKAbstractFESubSys::getElementDim()
    {
        //获取离散数据
        Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discModel)return -1;
        //FE模型
        Acoustics::FITKAcousticsFEModel* feModel = discModel->getFEModel();
        if (!feModel)return -1;
        FITKAcousticsFESubSysElementList* elementList = feModel->getFESubSysElementList();
        if (!elementList)return -1;
        int dim = -1;
        for (int eID : _elementsIDList)
        {
            Interface::FITKAbstractElement* element = elementList->getElementByID(eID);
            if (!element || dim == element->getElementDim())continue;
            if (dim == -1)
                dim = element->getElementDim();
            else
                return -1;
        }
        return dim;
    }

    void FITKAbstractFESubSys::setAllElementPropID(int propID)
    {
        //获取离散数据
        Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discModel)return;
        //FE模型
        Acoustics::FITKAcousticsFEModel* feModel = discModel->getFEModel();
        if (!feModel)return;
        FITKAcousticsFESubSysElementList* elementList = feModel->getFESubSysElementList();
        if (!elementList)return;
        for (int eID : _elementsIDList)
            elementList->setElementPropID(eID, propID);
    }

    void FITKAbstractFESubSys::setEnableState(bool state)
    {
        //设置启用状态
        _enabledState = state;
    }

    bool FITKAbstractFESubSys::getEnableState()
    {
        //获取启用状态
        return _enabledState;
    }

    void FITKAbstractFESubSys::setNote(QString note)
    {
        //设置注释
        _notes = note;
    }

    QString FITKAbstractFESubSys::getNote()
    {
        //获取注释
        return _notes;
    }

    bool FITKAbstractFESubSys::updateMesh(QHash<int, QList<int>> faceMeshData, QHash<int, int> elemSectionMap)
    {
        if (faceMeshData.isEmpty()) return false;
        //获取离散数据
        Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discModel)return false;
        //FE模型
        Acoustics::FITKAcousticsFEModel* feModel = discModel->getFEModel();
        Acoustics::FITKAcousticsDiscNodeList* nodeListDisc = discModel->getNodes();
        if (!feModel || !nodeListDisc)return false;
        //FE单元数据
        Acoustics::FITKAcousticsFESubSysElementList* feElementList = feModel->getFESubSysElementList();
        if (!feElementList) return false;
        //获取FE模型的映射表
        FITKAcousticsFENodeMapManager* feNodeMapMgr = feModel->getNodesMapManager();
        if (!feNodeMapMgr)return false;
        int elementMaxID = feElementList->getElementMaxID();
        //获取FE类型
        FITKAbstractFESubSys::FESubSysType typeFE = this->getFESubSysType();
        //单元链表
        QSet<int> nodeIDs;
        QList<Interface::FITKAbstractElement*> elementList;
        QList<int> elemPropList;
        for (QHash<int, QList<int>>::iterator iter = faceMeshData.begin(); iter != faceMeshData.end(); ++iter)
        {
            int partID = iter.key();
            QList<int> elemIDList = iter.value();
            if (elemIDList.isEmpty())continue;
            //获取部件和网格信息
            AbaqusData::FITKAbaqusPart* partData = FITKDATAREPO->getTDataByID<AbaqusData::FITKAbaqusPart>(partID);
            if (!partData)continue;
            Interface::FITKAbaMeshPartVTK* mesh = partData->getMesh();
            if (!mesh)continue;
            //获取FE模型映射表
            FITKAcousticsFENodeMap* feNodeMap = feNodeMapMgr->getFENodeMapByPartID(partID);
            if (!feNodeMap) continue;
            for (int elemID : elemIDList)
            {
                int propID = elemSectionMap.value(elemID);
                Interface::FITKAbstractElement* elemData = mesh->getElementByID(elemID);
                if (!elemData)continue;
                //添加维度判断
                int dim = elemData->getElementDim();
                if (typeFE == FITKAbstractFESubSys::FESubSysType::FEAcoustic && dim != 3)
                    continue;
                else if (typeFE == FITKAbstractFESubSys::FESubSysType::FEStructure && dim == 3)continue;
                //获取点
                QList<int> nodeIDList;
                int nodeCount = elemData->getNodeCount();
                for (int i = 0; i < nodeCount; ++i)
                {
                    int nodeID = elemData->getNodeID(i);
                    int nodeIDSEA = feNodeMap->getDiscNodeID(nodeID);
                    nodeIDList.append(nodeIDSEA);
                }
                Interface::FITKAbstractElement* element = Interface::FITKElementFactory::createElement(elemData->getEleType());
                if (!element)
                    continue;
                element->setEleID(++elementMaxID);
                element->setNodeID(nodeIDList);
                elementList.append(element);
                elemPropList.append(propID);
                //添加节点ID
                nodeIDs.unite(nodeIDList.toSet());
            }
        }
        //获取节点数据
        QList< Core::FITKNode*> nodeList;
        for (int nID : nodeIDs)
        {
            Core::FITKNode* nodeData = nodeListDisc->getNodeByID(nID);
            if (!nodeData) continue;
            nodeList.append(nodeData);
        }
        //创建分离板件工具
        Interface::FITKAbstractSeparatePlate* separatePlateTool = Interface::FITKAbstractSeparatePlate::createFITKSeparatePlate();
        if (!separatePlateTool) return false;
        //查看连续性
        QList<QList<int>> plateElemIndexs = separatePlateTool->getPlates(nodeList, elementList);
        //销毁分离板件工具
        delete separatePlateTool;
        separatePlateTool = nullptr;
        if (plateElemIndexs.size() > 1 || elementList.size() != elemPropList.size()) return false;
        for (int i = 0; i < elementList.size(); ++i)
        {
            Interface::FITKAbstractElement* element = elementList.at(i);
            if (!element) continue;
            int eleID = element->getEleID();
            feElementList->appendElement(element);
            feElementList->setElementPropID(eleID, elemPropList.at(i));
            _elementsIDList.append(eleID);
        }
        return true;
    }

    bool FITKAbstractFESubSys::updateMesh(Interface::FITKUnstructuredMesh* faceMeshData, int dim)
    {
        if (!faceMeshData) return false;
        //获取离散数据
        Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discModel)return false;
        //FE模型
        Acoustics::FITKAcousticsFEModel* feModel = discModel->getFEModel();
        Acoustics::FITKAcousticsDiscNodeList* nodeListDisc = discModel->getNodes();
        if (!feModel || !nodeListDisc)return false;
        //FE单元数据
        Acoustics::FITKAcousticsFESubSysElementList* feElementList = feModel->getFESubSysElementList();
        if (!feElementList) return false;
        //记录节点ID的映射表
        QHash<int, int> nodeIDsMap;
        //设置点数据
        int countNode = faceMeshData->getNodeCount();
        for (int i = 0; i < countNode; ++i)
        {
            Core::FITKNode* node = faceMeshData->getNodeAt(i);
            if (!node) continue;
            int id = nodeListDisc->addNode(node->x(), node->y(), node->z());
            nodeIDsMap.insert(node->getNodeID(), id);
        }
        //设置单元
        int elemIDMax = feElementList->getElementMaxID();
        int countElem = faceMeshData->getElementCount();
        if (countElem == 0) return false;
        _elementsIDList.clear();
        for (int i = 0; i < countElem; ++i)
        {
            Interface::FITKAbstractElement* element = faceMeshData->getElementAt(i);
            if (!element) continue;
            if (dim != element->getElementDim()) continue;
            //获取点
            QList<int> nodeIDList;
            int count = element->getNodeCount();
            for (int i = 0; i < count; ++i)
            {
                int nodeID = element->getNodeID(i);
                int nodeIDDisc = nodeIDsMap.value(nodeID);
                nodeIDList.append(nodeIDDisc);
            }
            Interface::FITKAbstractElement* elementDisc = Interface::FITKElementFactory::createElement(element->getEleType());
            if (!elementDisc) continue;
            elementDisc->setEleID(++elemIDMax);
            elementDisc->setNodeID(nodeIDList);
            feElementList->appendElement(elementDisc);
            _elementsIDList.append(elementDisc->getEleID());
        }
        return true;
    }


    QList<FITKAbstractFESubSys*> FITKAcousticsFESubSysManager::getSubSysByType(FITKAbstractFESubSys::FESubSysType type)
    {
        QList<FITKAbstractFESubSys*> subsys;
        //遍历全部对象
        const int n = this->getDataCount();
        for (int i = 0; i < n; ++i)
        {
            FITKAbstractFESubSys* sys = this->getDataByIndex(i);
            if (sys == nullptr) continue;
            //类型判断
            if (sys->getFESubSysType() == type)
                subsys.append(sys);
        }
        return subsys;
    }
}


